use adw::subclass::prelude::ObjectSubclassIsExt;
use gtk::glib::{self, object::ObjectExt};

use crate::ui::record_deletion_button::RecordDeletionButton;

glib::wrapper! {
    pub struct RecordItem(ObjectSubclass<imp::RecordItem>)
        @extends adw::Bin, gtk::Widget,
        @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget;
}

impl RecordItem {
    pub fn new(label: impl AsRef<str>) -> Self {
        let obj = glib::Object::new::<Self>();
        let imp = obj.imp();
        imp.name_label.set_label(label.as_ref());

        obj.connect_confirm_delete(glib::clone!(
            #[weak]
            obj,
            move || {
                log::warn!("Received `confirm-delete` signal in factory bind");
                obj.emit_by_name::<()>("request-delete", &[]);
            }
        ));

        obj
    }

    /// 获取标签文本
    pub fn label(&self) -> String {
        let imp = self.imp();
        imp.name_label.label().to_string()
    }

    /// 设置标签文本
    pub fn set_label(&self, label: impl AsRef<str>) {
        let imp = self.imp();
        imp.name_label.set_label(label.as_ref());
    }

    fn calc_level(&self) -> i32 {
        let mut i = 0;
        let imp = self.imp();
        match *imp.parent.borrow() {
            Some(ref parent) => {
                i = parent.calc_level() + 1;
            }
            None => {}
        }
        i
    }

    pub fn set_parent(&self, parent: Option<RecordItem>) {
        let imp = self.imp();
        *imp.parent.borrow_mut() = parent;

        // refresh level
        self.calc_level();
    }

    pub fn connect_confirm_delete<F>(&self, callback: F) -> glib::SignalHandlerId
    where
        F: Fn() + 'static,
    {
        let obj = self.imp();

        obj.deletion_button.connect_closure(
            "confirm-delete",
            false,
            glib::closure_local!(move |_: RecordDeletionButton| {
                callback();
            }),
        )
    }

    pub fn connect_request_delete<F>(&self, callback: F) -> glib::SignalHandlerId
    where
        F: Fn() + 'static,
    {
        self.connect_closure(
            "request-delete",
            false,
            glib::closure_local!(move |_: RecordItem| {
                callback();
            }),
        )
    }
}

mod imp {
    use std::cell::RefCell;

    use adw::{
        prelude::BinExt,
        subclass::{
            bin::BinImpl,
            prelude::{ObjectImpl, ObjectImplExt, ObjectSubclass, ObjectSubclassExt},
        },
    };
    use gtk::{
        glib::{self, object::ObjectExt},
        prelude::{BoxExt, OrientableExt, WidgetExt},
        subclass::widget::WidgetImpl,
    };

    use crate::ui::record_deletion_button::RecordDeletionButton;

    const SPACING: i32 = 10;

    #[derive(Default)]
    pub struct RecordItem {
        /// An horizontal box containing all the widgets.
        pub(super) container: gtk::Box,
        pub(super) is_directory: bool,
        pub(super) name_label: gtk::Label,
        pub(super) icon_image: gtk::Image,
        pub deletion_button: RecordDeletionButton,
        // starts from 0, indicating that it is not under any
        // folder.
        level: i32,
        pub(super) retract_space: adw::Bin,
        pub parent: RefCell<Option<super::RecordItem>>,
    }

    #[glib::object_subclass]
    impl ObjectSubclass for RecordItem {
        const NAME: &'static str = "RecordItem";
        type Type = super::RecordItem;
        type ParentType = adw::Bin;
    }

    impl ObjectImpl for RecordItem {
        fn signals() -> &'static [glib::subclass::Signal] {
            use std::sync::OnceLock;
            static SIGNALS: OnceLock<Vec<glib::subclass::Signal>> = OnceLock::new();
            SIGNALS.get_or_init(|| vec![glib::subclass::Signal::builder("request-delete").build()])
        }

        fn constructed(&self) {
            self.parent_constructed();

            // 设置缩进空间
            let retract_px = self.level * SPACING;
            if retract_px > 0 {
                self.retract_space.set_width_request(retract_px);
            }

            // 设置图标宽度
            self.icon_image.set_width_request(3);
            self.icon_image.set_icon_name(if self.is_directory {
                Some("folder-symbolic")
            } else {
                Some("document-symbolic")
            });

            // 配置标签
            self.name_label.set_hexpand(true);
            self.name_label.set_halign(gtk::Align::Start);
            self.name_label.set_valign(gtk::Align::Center);

            // 配置容器布局
            self.container.set_orientation(gtk::Orientation::Horizontal);
            self.container.set_spacing(6);
            self.container.set_hexpand(true);
            self.container.set_vexpand(true);
            self.container.set_margin_start(2);
            self.container.set_margin_end(2);
            self.container.set_margin_top(2);
            self.container.set_margin_bottom(2);

            // 添加子部件到容器
            self.container.append(&self.retract_space);
            self.container.append(&self.icon_image);
            self.container.append(&self.name_label);
            self.container.append(&self.deletion_button);

            // 将容器设置为 Bin 的子部件
            let obj = self.obj();
            obj.set_child(Some(&self.container));

            // obj.connect_confirm_delete(glib::clone!(
            //     #[weak]
            //     obj,
            //     move || {
            //         log::warn!("Received `confirm-delete` signal in factory bind");
            //         obj.emit_by_name::<()>("request-delete", &[]);
            //     }
            // ));
        }
    }

    impl WidgetImpl for RecordItem {}

    impl BinImpl for RecordItem {}
}
